package ru.mobiquest.utils.box2d;

import java.util.ArrayList;
import java.util.HashMap;

import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.entity.primitive.Rectangle;
import org.anddev.andengine.entity.shape.Shape;
import org.anddev.andengine.extension.physics.box2d.PhysicsConnector;
import org.anddev.andengine.extension.physics.box2d.PhysicsWorld;

import org.anddev.andengine.entity.scene.Scene;
import ru.mobiquest.utils.Polyline;

import android.location.Address;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.PolygonShape;

public class Box2dDebugRenderer implements IUpdateHandler {

	private HashMap<Body, ArrayList<Shape>> bodies = new HashMap<Body, ArrayList<Shape>>();
	private HashMap<Shape, Boolean> isSensorMap = new HashMap<Shape, Boolean>();
	
	private PhysicsWorld world;
	private Scene scene;
	private int debugLayerIndex;
	
	public Box2dDebugRenderer(PhysicsWorld world, Scene scene, int debugLayerIndex) {
		this.world = world;
		this.scene = scene;
		this.debugLayerIndex = debugLayerIndex;
	}
	
	@Override
	public void onUpdate(float pSecondsElapsed) {
		float ptm = PhysicsConnector.PIXEL_TO_METER_RATIO_DEFAULT;
		
		// Find new bodies and add them to the managed hashset
		for(Body body : world.getBodies()) {
			// Detect if it's not yet in the hash
			if(!bodies.containsKey(body)) {
				addBodyToShapeCollection(body);
			}
			
			// Iterate through the list of shapes, 
			// updating their location and rotation
			ArrayList<Shape> shapes = bodies.get(body);
			
			for(Shape shape : shapes) {
				Shape bodyShape = shape;
				
				bodyShape.setAlpha(0.35f);
				
				if(body.isAwake())
					bodyShape.setColor(255, 0, 0);
				if(isSensorMap.containsKey(shape))
					bodyShape.setColor(55, 55, 255);
				else
					bodyShape.setColor(180, 0, 0);
				
				bodyShape.setRotationCenter(body.getMassData().center.x * ptm, body.getMassData().center.y * ptm);
				bodyShape.setRotation((float) (body.getAngle() * (180 / Math.PI)));
				
//				bodyShape.setPosition(body.getPosition().x * PhysicsConnector.PIXEL_TO_METER_RATIO_DEFAULT - bodyShape.getWidth() / 2, 
//						body.getPosition().y * PhysicsConnector.PIXEL_TO_METER_RATIO_DEFAULT - bodyShape.getHeight() / 2);
				
				bodyShape.setPosition(body.getPosition().x * ptm, 
						body.getPosition().y * ptm);
			}
		}
	}
	
	private void addBodyToShapeCollection(Body body) {
		bodies.put(body, new ArrayList<Shape>());
		
		// Create fixture shapes for the body
		for(Fixture fixture : body.getFixtureList()) {
			PolygonShape fixtureShape = (PolygonShape) fixture.getShape();
			if(fixtureShape == null) continue;
			
//			if(fixtureShape.getVertexCount() == 114) {
//				Vector2 vertex1 = new Vector2(), vertex2 = new Vector2(), vertex3 = new Vector2(), vertex4 = new Vector2();
//				
//				fixtureShape.getVertex(0, vertex1);
//				fixtureShape.getVertex(1, vertex2);
//				fixtureShape.getVertex(2, vertex3);
//				fixtureShape.getVertex(3, vertex4);
//				
//				Shape debugShape = new Rectangle(0, 0, Math.abs(vertex2.x - vertex1.x) * PhysicsConnector.PIXEL_TO_METER_RATIO_DEFAULT, 
//						Math.abs(vertex3.y - vertex2.y) * PhysicsConnector.PIXEL_TO_METER_RATIO_DEFAULT);
//				
//				bodies.get(body).add(debugShape);
//				
//				if(fixture.isSensor())
//					isSensorMap.put(debugShape, true);
//				
//				scene.getLayer(debugLayerIndex).addEntity(debugShape);
//			}
//			else { // Create a polygon shape
			ArrayList<Float> xPoints = new ArrayList<Float>();
			ArrayList<Float> yPoints = new ArrayList<Float>();
			Vector2 vertex = new Vector2();
			
			for(int i = 0; i < fixtureShape.getVertexCount(); i++) {
				fixtureShape.getVertex(i, vertex);
				xPoints.add(vertex.x * PhysicsConnector.PIXEL_TO_METER_RATIO_DEFAULT);
				yPoints.add(vertex.y * PhysicsConnector.PIXEL_TO_METER_RATIO_DEFAULT);
			}
			
			Shape debugShape = new Polyline(xPoints, yPoints);
			
			bodies.get(body).add(debugShape);
			
			if(fixture.isSensor())
				isSensorMap.put(debugShape, true);
			
			scene.getLayer(debugLayerIndex).addEntity(debugShape);
//			}
		}
	}

	@Override
	public void reset() {
		// TODO Auto-generated method stub
	}

}
